package com.chao.common.config.controlle;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.chao.common.config.controlle.DateConverter;
import com.chao.common.config.controlle.Decimal;
import com.chao.common.config.dic.DicKey;
import com.chao.common.config.dic.DicSerialize;
import com.chao.common.util.StrUtile;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;

import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 日期转换配置 * 解决@RequestAttribute、@RequestParam和@RequestBody三种类型的时间类型参数接收与转换问题
 */
@Configuration
public class DateConfig {

    public static ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 默认日期时间格式
     */
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * Date转换器，用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, Date> dateConverter() {
        return new com.chao.common.config.controlle.DateConverter();
    }

    /**
     * Json序列化和反序列化转换器，用于转换Post请求体中的json以及将我们的对象序列化为返回响应的json * 使用@RequestBody注解的对象中的Date类型将从这里被转换
     */
    @Bean
    public ObjectMapper objectMapper() {
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
        JavaTimeModule javaTimeModule = new JavaTimeModule(); //Date序列化和反序列化
        javaTimeModule.addSerializer(Short.class, new DicSerialize());
        javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
            @Override
            public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                try {
                    SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                    String formattedDate = formatter.format(date);
                    if(formattedDate.contains(" 00:00:00")){
                        formattedDate = formattedDate.replace(" 00:00:00","");
                    }
                    jsonGenerator.writeString(formattedDate);
                } catch (Exception ignored) {
                    jsonGenerator.writeString("");
                }
            }
        });
        javaTimeModule.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
            @Override
            public void serialize(LocalDateTime date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                try {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT);
                    String formattedDate = formatter.format(date);
                    if(formattedDate.contains(" 00:00:00")){
                        formattedDate = formattedDate.replace(" 00:00:00","");
                    }
                    jsonGenerator.writeString(formattedDate);
                } catch (Exception ignored) {
                    jsonGenerator.writeString("");
                }
            }
        });
        javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                return new DateConverter().convert(jsonParser.getText());
            }
        });
        javaTimeModule.addDeserializer(String.class, new JsonDeserializer<String>() {
            @Override
            public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                return StrUtile.isEmpty(jsonParser.getText())?null:jsonParser.getText();
            }
        });
        javaTimeModule.addDeserializer(Short.class, new JsonDeserializer<Short>() {
            @Override
            public Short deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                try {
                    Class<?> a = jsonParser.getCurrentValue().getClass();
                    Field b = a.getDeclaredField(jsonParser.getCurrentName());
                    if(b.isAnnotationPresent(DicKey.class)){
                        return 0;
                    }
                } catch (NoSuchFieldException ignored) {}
                return jsonParser.getShortValue();
            }
        });
        javaTimeModule.addSerializer(Double.class, new JsonSerializer<Double>() {
            @Override
            public void serialize(Double date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                try {
                    String str = "#.##";
                    Class<?> a = jsonGenerator.getOutputContext().getCurrentValue().getClass();

                    Field b = a.getDeclaredField(jsonGenerator.getOutputContext().getCurrentName());
                    if(b.isAnnotationPresent(com.chao.common.config.controlle.Decimal.class)){
                        com.chao.common.config.controlle.Decimal decimal = b.getAnnotation(Decimal.class);
                        str = decimal.value();
                    }
                    DecimalFormat df = new DecimalFormat(str);
                    jsonGenerator.writeString(df.format(date));
                } catch (Exception ignored) {
                    jsonGenerator.writeString(StrUtile.isEmpty(date) ? "0" : date+"");
                }
            }
        });
        javaTimeModule.addSerializer(BigDecimal.class, new JsonSerializer<BigDecimal>() {
            @Override
            public void serialize(BigDecimal date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                try {
                    DecimalFormat df = new DecimalFormat("#.##");
                    jsonGenerator.writeString(df.format(date));
                } catch (Exception ignored) {
                    jsonGenerator.writeString(StrUtile.isEmpty(date) ? "0" : date.toString());
                }
            }
        });
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }
}
